package com.berchen.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.berchen.common.KeyEnum;
import com.berchen.common.busidb.model.BillExcelVo;
import com.berchen.common.busidb.model.BillQueryModel;
import com.berchen.common.busidb.model.BillVo;
import com.berchen.common.busidb.service.BusidbService;
import com.berchen.common.result.Result;
import com.berchen.common.result.ResultEnum;
import com.berchen.listener.BusiExcelListener;
import com.berchen.utils.DateTimeUtils;
import com.berchen.utils.Log4jUtils;
import com.berchen.utils.OssUtils;
import com.berchen.utils.RedisUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@RequestMapping("busi/")
@Controller
//@CrossOrigin(origins = "*",maxAge = 3600)
public class BusiController {

    private static Logger logger=Logger.getLogger(BusiController.class);
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private BusidbService service;


    /**
     * 删除账单
     * @param id
     * @param request
     * @return
     */
    @DeleteMapping("delBill.cwh/{id}")
    @ResponseBody
    public Result delBill(@PathVariable Long id,HttpServletRequest request){
        try{

            String token=request.getHeader("token");
            String uid= (String) redisUtils.get(KeyEnum.USER_TOKEN.getKey()+token);
            service.delBill(id,Long.parseLong(uid));
            return Result.ok();
        }catch (Exception e){
            logger.error(Log4jUtils.getTrace(e));
            return Result.error();
        }
    }

    /**
     * 查询账单 并且分页
     * @param vo
     * @return
     */
    @GetMapping("getBill.cwh")
    @ResponseBody
    public Result getBill(@Valid BillQueryModel vo){
        try{
            // 日期验证
            try{
                if(!StringUtils.isEmpty(vo.getSDate())){
                    LocalDate.parse(vo.getSDate());
                }
                if(!StringUtils.isEmpty(vo.getEDate())){
                    LocalDate.parse(vo.getEDate());
                }
                if(!StringUtils.isEmpty(vo.getMonthDate())){
                    vo.setSDate(DateTimeUtils.getFirstDayOfMonth(LocalDate.parse(vo.getMonthDate())));
                    vo.setEDate(DateTimeUtils.getLastDayOfMonth(LocalDate.parse(vo.getMonthDate())));
                }
            }catch (Exception e){
                return Result.set(ResultEnum.DATE_FORMAT_ERROR);
            }
            vo.updateNum(); // 更改num的值
            if(!vo.checkOrder()){   // 检查排序字段是否正确
                return Result.set(ResultEnum.ORDER_ERROR);
            }
            List<BillVo> bills=service.getBillsByCondition(vo);
            vo.setNum(null);
            List<BillVo> countList=service.getBillsByCondition(vo);
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("data",bills);
            jsonObject.put("count",countList==null?0:countList.size());

            Double inPrice=null;
            Double outPrice=null;
            if(!StringUtils.isEmpty(vo.getMonthDate())){
                // 查询 月收入 支出
                vo.setType(0);  // 支出

                inPrice=service.getPrice(vo);
                vo.setType(1);
                outPrice=service.getPrice(vo);

                jsonObject.put("inPrice",Math.abs(inPrice));
                jsonObject.put("outPrice",Math.abs(outPrice));

            }
            return Result.ok(jsonObject);
        }catch(Exception e){

            logger.error(Log4jUtils.getTrace(e));
            return Result.error();
        }
    }

    /**
     * 单条添加账单数据
     * @param vo
     * @return
     */
    @PutMapping("addBill.cwh")
    @ResponseBody
    public Result addBill(@RequestBody @Valid BillVo vo){
        try{
            // 根据token获取用户信息
//            String uid= (String) redisUtils.get(KeyEnum.USER_TOKEN.getKey()+vo.getToken());
//            if(StringUtils.isEmpty(uid)){
//                return Result.set(ResultEnum.NO_LOGIN);
//            }
//            vo.setUid(Long.parseLong(uid));

            if(StringUtils.isEmpty(vo.getCreateDate())){
                try {
                    LocalDate.parse(vo.getCreateDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                }catch (Exception e){
                    return Result.set(ResultEnum.DATE_FORMAT_ERROR);
                }
            }
            // 添加单条账务
            service.addBill(vo);
        }catch (Exception e){
            logger.error(Log4jUtils.getTrace(e));
            return Result.error();
        }
        return Result.ok();

    }

    /**
     * 批量添加账务
     * @param file   要上传的文件 文件名 file
     * @return
     */
    @PutMapping("batchAddBill.cwh")
    @ResponseBody
    public Result batchAddBill(@RequestParam("file") MultipartFile file,HttpServletRequest request){

        try {

            String filename = file.getOriginalFilename();
            if(!filename.endsWith(".xls")&&!filename.endsWith(".xlsx")){
                Result set = Result.set(ResultEnum.FILE_TYPE_ERROR);
                set.setData("请上传.xls或.xlsx后缀的文件");
                return set;
            }

            List<BillVo> bills=new ArrayList<>();
            /**
             * 将数据从Excel中读取到对象中
             * 第一个参数：文件流
             * 第二个参数：读取到的文件转化成的实体类
             * 第三个参数：监听器 每行进行读取 然后进行操作
             */
            EasyExcel.read(file.getInputStream(), BillExcelVo.class,new BusiExcelListener(bills)).sheet().doRead();

            String token = request.getHeader("token");
            String uid= (String) redisUtils.get(KeyEnum.USER_TOKEN.getKey()+token);
            // 将数据 的uid 设置为1   应该是从登陆的用户的缓存中获取用户ID的
            bills.stream().forEach(bill->{bill.setUid(Long.parseLong(uid));});
            // 操作数据库
            service.batchAddBill(bills);
            return Result.ok();
        }
        catch (Exception e){
            logger.error("批量添加账单数据错误"+Log4jUtils.getTrace(e));
            return Result.error();
        }
    }

    /**
     * 批量导出该用户所有数据
     * @param response
     */
    @GetMapping("uploadBills.cwh")
    public void uploadBills(HttpServletResponse response,HttpServletRequest request){
        uploadBills(response,request,null);
    }

    /**
     * 批量导该用户这个月的账单数据
     * @param response
     */
    @GetMapping("uploadBills.cwh/{date}")
    public void uploadBills(HttpServletResponse response, HttpServletRequest request, @PathVariable("date") String date){

        try {
            // 设置请求头
            response.setContentType("application/vnd.ms.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码，当然和easyExcel没有关系
            String fileName= URLEncoder.encode("账单数据","utf-8");
            response.setHeader("Content-disposition","attachment;filename="+fileName+".xlsx");

            BillQueryModel vo=new BillQueryModel();
            String token = request.getHeader("token");
            String uid= (String) redisUtils.get(KeyEnum.USER_TOKEN.getKey()+token);
            vo.setUid(Long.parseLong(uid));
            if(!StringUtils.isEmpty(date)) {    // 根据这个作为查询条件是查询这一个月的还是查询该用户的所有账户信息
                LocalDate parse = LocalDate.parse(date+"-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                vo.setSDate(DateTimeUtils.getFirstDayOfMonth(parse));
                vo.setEDate(DateTimeUtils.getLastDayOfMonth(parse));
            }
            List<BillExcelVo > excelVo=new ArrayList<>();
            // 查询数据库
            List<BillVo>bills=service.getBillsByCondition(vo);
            bills.stream().forEach(bill->{
                bill.setTypeStr(bill.getType().equals(0)?"支出":"收入");
                BillExcelVo billExcelVo = new BillExcelVo();
                BeanUtils.copyProperties(bill,billExcelVo);
                excelVo.add(billExcelVo);
            });

            // 将数据写入到excel 文件中
            EasyExcel.write(response.getOutputStream(),BillExcelVo.class).sheet(date).doWrite(excelVo);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 下载文件 另外一种写法
     */
    @GetMapping("download")
    public ResponseEntity<byte[]> uploadBills1( HttpServletRequest request){

        FileInputStream is=null;
        HttpHeaders httpHeaders=new HttpHeaders();
        try {

            String fileName= URLEncoder.encode("log4j.properties","utf-8");
            httpHeaders.set("Content-disposition","attachment;filename="+fileName);     // 告诉服务器使用下载方式打开文件

            String realPath = this.getClass().getClassLoader().getResource(fileName).getPath();
            is=new FileInputStream(realPath);
            byte[] bytes=new byte[is.available()];
            is.read(bytes); //将文件读到字节数组中

            return new ResponseEntity<byte[]>(bytes,httpHeaders, HttpStatus.OK);

        }catch (Exception e){
            e.printStackTrace();
            httpHeaders.set("Content-type","test/html;charset=utf-8");
            return new ResponseEntity<byte[]>("系统异常".getBytes(), HttpStatus.OK);
        }
        finally {
            if(is!=null) {
                try {
                    is.close(); //关闭流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
